package GoodsActivityService

import (
	"context"
	"fmt"
	"gdshop-font-api-go/app/entity"
	"gdshop-font-api-go/app/response/GoodsResp"
	toolsDb "gdshop-font-api-go/library/tools/db"
	"github.com/gogf/gf/encoding/gjson"
	"sort"
	"strings"
)

// GetGoodsActivityByGoodsId 根据商品ID获取适合的活动列表
func GetGoodsActivityByGoodsId(ctx context.Context, goodsId int) ([]*entity.GoodsActivity, error) {
	// 找到活动时间内的活动
	var tmpList []*entity.GoodsActivity
	err := toolsDb.GetUnSafaTable(ctx, "goods_activity").Where(
		"ga.delete_at<1 AND ga.status = ? AND (ga.start_time <= UNIX_TIMESTAMP(NOW()) AND ga.end_time >= UNIX_TIMESTAMP(NOW()))",
		1,
	).As("ga").LeftJoin("goods_activity_rule gar", "gar.activity_id = ga.id").
		Fields("ga.*,gar.rules,gar.loop").Order("ga.sort DESC,ga.id ASC").
		Scan(&tmpList)
	if err != nil {
		return nil, err
	}
	//var gaList []*entity.GoodsActivity
	for k, item := range tmpList {
		// 去掉排除商品ID的活动
		if item.GoodsType == 2 && item.GoodsIds.Contains(goodsId) {
			// 在其中的
			tmpList = append(tmpList[:k], tmpList[k+1:]...)
		}
		// 如果活动不包含商品ID，也去掉
		if item.GoodsType == 1 && !item.GoodsIds.Contains(goodsId) {
			if len(tmpList) < 2 {
				// 判断如果不够减了，直接赋值
				tmpList = []*entity.GoodsActivity{}
			} else {
				tmpList = append(tmpList[:k], tmpList[k+1:]...)
			}
		}
		// 2022.06.12 添加判断，排除商品ID
		if item.ExcludeGoodsIds != nil && item.ExcludeGoodsIds.Contains(goodsId) {
			// 从数组里面删除本 item
			tmpList = append(tmpList[:k], tmpList[k+1:]...)
		}
	}

	// 按最优惠
	// 满减，取最高的那条优惠，算出比例
	// 满折，取最高的那条优惠的比例
	for _, item := range tmpList {
		item.DiscountRatio = clacDiscountRatio(item)
	}
	// 根据优惠排序
	sort.Slice(tmpList, func(i, j int) bool {
		return tmpList[i].DiscountRatio < tmpList[j].DiscountRatio
	})

	return tmpList, nil
}

func GetGoodsActivityById(ctx context.Context, id int) (*entity.GoodsActivity, error) {
	// 找到活动时间内的活动
	var tmpModel *entity.GoodsActivity
	err := toolsDb.GetUnSafaTable(ctx, "goods_activity").Where(
		"ga.delete_at<1 AND ga.status = ? AND (ga.start_time <= UNIX_TIMESTAMP(NOW()) AND ga.end_time >= UNIX_TIMESTAMP(NOW()))",
		1,
	).Where("id", id).As("ga").LeftJoin("goods_activity_rule gar", "gar.activity_id = ga.id").
		Fields("ga.*,gar.rules,gar.loop").Order("ga.sort DESC,ga.id ASC").
		Scan(&tmpModel)
	if err != nil {
		return nil, err
	}

	return tmpModel, nil
}

// 解析路由规则
func AnalysisRule(ruleStr string) ([]*entity.RulesItem, error) {
	json, err := gjson.LoadContent(ruleStr)
	if err != nil {
		return nil, err
	}
	var tmps []*entity.RulesItem
	err = json.Structs(&tmps)
	if err != nil {
		return nil, err
	}
	return tmps, nil
}

// 计算一条数据优惠比例 ， 只计算 activity_type = 1 和 activity_type = 2 的情况
func clacDiscountRatio(p *entity.GoodsActivity) float64 {
	if p.ActivityType != 1 && p.ActivityType != 2 {
		// 不支持类型，直接返回
		return 0
	}

	// 解析规则
	ruleList, err := AnalysisRule(p.Rules)
	if err != nil {
		panic("解析规则失败：" + err.Error())
	}
	if len(ruleList) < 1 {
		// 防止出错
		panic("解析规则失败：长度为0")
	}

	// 排序，选出最优惠的排在第一位
	sort.Slice(ruleList, func(i, j int) bool {
		return clacDiscountRatioOne(ruleList[i], p.ActivityType) < clacDiscountRatioOne(ruleList[j], p.ActivityType)
	})

	return clacDiscountRatioOne(ruleList[0], p.ActivityType)
}

// 计算单项优惠比例
func clacDiscountRatioOne(one *entity.RulesItem, activityType int) float64 {
	// 减
	if activityType == 2 {
		// 每满减实际就是折扣
		return 1 - float64(one.DiscountNum)/float64(one.ThresholdNum)
	}
	// 折
	if activityType == 1 {
		return float64(one.DiscountNum) / 1000.00
	}

	return 0
}

// GetGoodsActivityTagByGoodsId 根据商品ID获取活动标签
func GetGoodsActivityTagByGoodsId(ctx context.Context, goodsId int) ([]*GoodsResp.ActivityTagItem, error) {
	gaList, err := GetGoodsActivityByGoodsId(ctx, goodsId)
	if err != nil {
		return nil, err
	}
	jieguo := []*GoodsResp.ActivityTagItem{}
	for _, item := range gaList {
		jieguo = append(jieguo, &GoodsResp.ActivityTagItem{
			Id:     item.Id,
			Type:   GetActivityTagTypeStr(item),
			Remark: item.Remark,
		})
	}
	return jieguo, nil
}

func GetActivityTagTypeStr(m *entity.GoodsActivity) string {
	// 1打折；2满减；3秒杀价；4送优惠券 5送赠品
	switch m.ActivityType {
	case 1:
		return "满折"
	case 2:
		return "满减"
	case 3:
		return "秒杀"
	case 4:
		return "送券"
	case 5:
		return "赠品"
	}

	return "未知"
}

func getActivityTagRemark(m *entity.GoodsActivity) string {
	if m.Rules == "" {
		return ""
	}
	// 1打折；2满减；3秒杀价；4送优惠券 5送赠品
	remark := ""
	if m.Loop > 0 {
		remark = "每"
	}
	rules := []*GoodsResp.GoodsActivityRuleItem{}
	json, err := gjson.LoadContent(m.Rules)
	if err != nil {
		return err.Error()
	}
	err = json.Structs(&rules)
	if err != nil {
		return err.Error()
	}
	ruleTexts := []string{}
	for _, item := range rules {
		if item.ThresholdNum < 1 {
			ruleTexts = append(ruleTexts, "无门槛")
		} else {
			ruleTexts = append(ruleTexts, remark+"满"+
				(fmt.Sprintf("%.2f", float64(item.ThresholdNum)/float64(100)))+"元")
		}
		switch m.ActivityType {
		case 1:
			ruleTexts = append(ruleTexts, "打"+
				(fmt.Sprintf("%.2f", float64(item.ThresholdNum)/float64(100)))+"折")
			break
		case 2:
			ruleTexts = append(ruleTexts, "可减"+
				(fmt.Sprintf("%.2f", float64(item.ThresholdNum)/float64(100)))+"元")
			break
		}
	}

	return strings.Join(ruleTexts, ",")
}

// GetMaxDiscountActivity 取到最大优惠的活动，第一个参数有可能返回 nil 说明没有匹配的活动
// activitys 当前商品参与的活动列表
func GetMaxDiscountActivity(activitys []*entity.GoodsActivity, totalPrice int64) (*entity.GoodsActivity,
	int64, error) {
	var discountMoney int64 = 0
	nowActivity := (*entity.GoodsActivity)(nil)

	for _, item := range activitys {
		// 暂时先处理 activity_type == 1 == 2 的情况
		if item.ActivityType != 1 && item.ActivityType != 2 {
			continue
		}

		// 解析规则
		tmps, err := AnalysisRule(item.Rules)
		if err != nil {
			return nil, 0, err
		}
		if len(tmps) < 1 {
			// 防止出错
			continue
		}

		// 处理 loop == 1 的
		if item.Loop == 1 {
			// 每满 减(折)
			if tmps[0].ThresholdNum > totalPrice {
				// 总支付金额 不超过 门槛
				continue
			}
			var tmpDiscountMoney float64 = 0
			// 减
			if item.ActivityType == 2 {
				// 先算出循环次数
				num := totalPrice / tmps[0].ThresholdNum
				tmpDiscountMoney = float64(tmps[0].DiscountNum * num)
			}
			// 折
			if item.ActivityType == 1 {
				// 折 TODO 这里有点疑义，后面再测试
				tmpDiscountMoney = float64(totalPrice) - float64(totalPrice)*
					float64(tmps[0].DiscountNum)/1000.00
			}
			if discountMoney > int64(tmpDiscountMoney) {
				continue
			}
			discountMoney = int64(tmpDiscountMoney)
			nowActivity = item
		} else {
			for _, r := range tmps {
				if r.ThresholdNum > totalPrice {
					continue
				}

				var tmpDiscountMoney float64 = 0
				// 减
				if item.ActivityType == 2 {
					tmpDiscountMoney = float64(r.DiscountNum)
				}
				// 折
				if item.ActivityType == 1 {
					tmpDiscountMoney = float64(totalPrice) - float64(totalPrice)*
						float64(r.DiscountNum)/1000.00
				}

				if discountMoney > int64(tmpDiscountMoney) {
					// 上一个优惠金额，大于当前，则循环下一个活动
					continue
				}

				discountMoney = int64(tmpDiscountMoney)
				nowActivity = item
			}
		}
		//fmt.Println("----------------选中 ", nowActivity, " 优惠 ", discountMoney)
	}

	return nowActivity, discountMoney, nil
}

func GetMaxDiscountActivityByGoodsId(ctx context.Context, goodsId int, totalPrice int64) (*entity.GoodsActivity,
	int64, error) {

	activitys, err := GetGoodsActivityByGoodsId(ctx, goodsId)
	if err != nil {
		return nil, 0, err
	}

	var discountMoney int64 = 0
	nowActivity := (*entity.GoodsActivity)(nil)

	for _, item := range activitys {
		// 暂时先处理 activity_type == 1 == 2 的情况
		if item.ActivityType != 1 && item.ActivityType != 2 {
			continue
		}

		// 解析规则
		json, err := gjson.LoadContent(item.Rules)
		if err != nil {
			return nil, 0, err
		}
		var tmps []*entity.RulesItem
		err = json.Structs(&tmps)
		if err != nil {
			return nil, 0, err
		}
		if len(tmps) < 1 {
			// 防止出错
			continue
		}

		// 处理 loop == 1 的
		if item.Loop == 1 {
			// 每满 减(折)
			if tmps[0].ThresholdNum > totalPrice {
				// 总支付金额 不超过 门槛
				continue
			}
			var tmpDiscountMoney float64 = 0
			// 减
			if item.ActivityType == 2 {
				// 每满减实际就是折扣
				tmpDiscountMoney = float64(totalPrice) *
					float64(tmps[0].DiscountNum) / float64(tmps[0].ThresholdNum)
			}
			// 折
			if item.ActivityType == 1 {
				tmpDiscountMoney = float64(totalPrice) - float64(totalPrice)*
					float64(tmps[0].DiscountNum)/1000.00
			}
			if discountMoney > int64(tmpDiscountMoney) {
				continue
			}
			discountMoney = int64(tmpDiscountMoney)
			nowActivity = item
		} else {
			for _, r := range tmps {
				if r.ThresholdNum > totalPrice {
					continue
				}

				var tmpDiscountMoney float64 = 0
				// 减
				if item.ActivityType == 2 {
					// 每满减实际就是折扣
					tmpDiscountMoney = float64(r.DiscountNum)
				}
				// 折
				if item.ActivityType == 1 {
					tmpDiscountMoney = float64(totalPrice) - float64(totalPrice)*
						float64(tmps[0].DiscountNum)/1000.00
				}

				if discountMoney > int64(tmpDiscountMoney) {
					// 上一个优惠金额，大于当前，则循环下一个活动
					continue
				}

				discountMoney = int64(tmpDiscountMoney)
				nowActivity = item
			}
		}

		fmt.Println("----------------选中 ", nowActivity, " 优惠 ", discountMoney)
	}

	return nowActivity, discountMoney, nil
}
